/// @file MainApp.cpp
/// @brief the main gui application class, extended from the
/// MainWindow_ui and holds all the UI and our main gl window

#include "MainApp.h"
#include "Configuration.h"

#include "ui_MainWindow.h"



MainApp::MainApp
                (
                    QWidget* _parent
                ):
                QMainWindow(_parent),
                m_ui(new Ui::MainWindow)
{
    // setup the user interface
    m_ui->setupUi(this);

    //create a new instance of the world and give it an initial aspect ratio
    m_simulation = new Simulation(this);

    m_ui->s_mainGridLayout->addWidget(m_simulation, 0, 0, 4, 2);

    //setup signals/slots
    setupConnections();
}

MainApp::~MainApp()
{
    delete m_ui;
}

void MainApp::setupConnections()
{
    //read from simulation objects and initialise states of controls

    //---------------------------------------------------------------------------------------------------------------------
    //TAB : SOLVER
    //timestep
    m_ui->spin_solver_timestep->setValue(m_simulation->getIntegration()->getTimestep());

    //smoothing length
    m_ui->spin_solver_smoothingLength->setValue(m_simulation->getSolver()->getSmoothingLength());


    //---------------------------------------------------------------------------------------------------------------------
    //TAB : FLUID
    ///build fluid name list
    for (int i = 0; i < m_simulation->getSolver()->getNameList().size(); ++i)
    {
        m_ui->cmb_fluid_currentFluid->addItems(QStringList(QString(m_simulation->getSolver()->getNameList()[i].c_str())));
    }

    //update controls for the first fluid
    if (m_simulation->getSolver()->getNameList().size() >= 1) refreshControlsFromFluid(0);

    //toggle hose marker drawing
    m_ui->chk_fluid_hose_drawMarker->setChecked(m_simulation->getSolver()->getDrawHoseMarker());

    //hose centre
    m_ui->spin_hose_centre_x->setValue(m_simulation->getSolver()->getHoseCenter().m_x);
    m_ui->spin_hose_centre_y->setValue(m_simulation->getSolver()->getHoseCenter().m_y);
    m_ui->spin_hose_centre_z->setValue(m_simulation->getSolver()->getHoseCenter().m_z);

    //hose velocity
    m_ui->spin_hose_velocity_x->setValue(m_simulation->getSolver()->getHoseVelocity().m_x);
    m_ui->spin_hose_velocity_y->setValue(m_simulation->getSolver()->getHoseVelocity().m_y);
    m_ui->spin_hose_velocity_z->setValue(m_simulation->getSolver()->getHoseVelocity().m_z);

    //wait until first time properties
    m_ui->chk_fluid_hose_waitUntilBoundary->setChecked(m_simulation->getSolver()->getHoseWaitUntilHitBoundary());
    m_ui->chk_fluid_hose_waitUntilRBD->setChecked(m_simulation->getSolver()->getHoseWaitUntilHitRBD());


    //---------------------------------------------------------------------------------------------------------------------
    //TAB : CACHE
    //cache toggle
    m_ui->chk_cache_enable->setChecked(m_simulation->getCacheEnabled());

    //cache sampling interval
    m_ui->spin_cache_samplingInterval->setValue(m_simulation->getCacheSamplingInterval());

    //cache automatic sampling
    m_ui->chk_cache_automaticFlush->setChecked(m_simulation->getCacheAutomaticFlushEnabled());
    m_ui->spin_cache_automaticFlushInterval->setValue(m_simulation->getCacheAutomaticFlushInterval() / 1000);   //ms -> s

    //cache rbd and boundary
    m_ui->chk_cache_exportRBD->setChecked(m_simulation->getCacheExportRBDEnabled());
    m_ui->chk_cache_exportBoundary->setChecked(m_simulation->getCacheExportBoundaryEnabled());


    //---------------------------------------------------------------------------------------------------------------------
    //TAB : ENVIRONMENT

    //SUBTAB : BOUNDARY
    //boundary centre
    m_ui->spin_environment_boundary_centre_x->setValue(m_simulation->getEnvironment()->getBoundaryPosition().m_x);
    m_ui->spin_environment_boundary_centre_y->setValue(m_simulation->getEnvironment()->getBoundaryPosition().m_y);
    m_ui->spin_environment_boundary_centre_z->setValue(m_simulation->getEnvironment()->getBoundaryPosition().m_z);

    //boundary dimension
    m_ui->spin_environment_boundary_size_x->setValue(m_simulation->getEnvironment()->getBoundaryDimension().m_x);
    m_ui->spin_environment_boundary_size_y->setValue(m_simulation->getEnvironment()->getBoundaryDimension().m_x);
    m_ui->spin_environment_boundary_size_z->setValue(m_simulation->getEnvironment()->getBoundaryDimension().m_x);

    //restitution coefficients
    m_ui->spin_environment_boundary_restitutionForFluid->setValue(m_simulation->getEnvironment()->getBoundaryRestitutionCoefficientForFluid());
    m_ui->spin_environment_boundary_restitutionForRBD->setValue(m_simulation->getEnvironment()->getBoundaryRestitutionCoefficientForRBD());

    //periodic wall
    m_ui->chk_environment_boundary_enablePeriodicWall->setChecked(m_simulation->getEnvironment()->getPeriodicWallEnabled());
    m_ui->spin_environment_boundary_periodicWall_speed->setValue(m_simulation->getEnvironment()->getPeriodicWallSpeed());
    m_ui->spin_environment_boundary_periodicWall_angleIncrement->setValue(m_simulation->getEnvironment()->getPeriodicWallAngleIncrement());
    m_ui->spin_environment_boundary_periodicWall_maxAmplitude->setValue(m_simulation->getEnvironment()->getPeriodicWallMaxAmplitude());


    //SUBTAB : RBD
    //restitution coefficients
    m_ui->spin_environment_rbd_restitution->setValue(m_simulation->getEnvironment()->getObstacleRestitutionCoefficient());

    //capsule resolution
    m_ui->spin_environment_capsule_resolution->setValue(m_simulation->getEnvironment()->getCapsuleResolution());

    //build sphere combo list
    for (int i = 0; i < m_simulation->getEnvironment()->getSphereNameList().size(); ++i)
    {
        m_ui->cmb_environment_sphere->addItems(QStringList(QString(m_simulation->getEnvironment()->getSphereNameList()[i].c_str())));
    }

    //update controls for the first sphere
    if (m_simulation->getEnvironment()->getSphereNameList().size() >= 1) refreshControlsFromSphere(0);

    //build sphere combo list
    for (int i = 0; i < m_simulation->getEnvironment()->getCapsuleNameList().size(); ++i)
    {
        m_ui->cmb_environment_capsule->addItems(QStringList(QString(m_simulation->getEnvironment()->getCapsuleNameList()[i].c_str())));
    }

    //update controls for the first capsule
    if (m_simulation->getEnvironment()->getCapsuleNameList().size() >= 1) refreshControlsFromCapsule(0);


    //OUTSIDE BUTTONS
    m_ui->cmd_autoMove->setText(m_simulation->getSolver()->getEnableAutoFluidUpdate() ? "AutoMove Stop" : "AutoMove Start");


    //GLOBAL CAMERA
    //setup camera zoom control and signal here
    //read camera z value from config file and set it to the slider
    ngl::Camera m_camera = Configuration::initialiseCamera(1.0);
    m_ui->sld_cameraZoom->setValue(-m_camera.getEye().m_z);
    connect(m_ui->sld_cameraZoom, SIGNAL(valueChanged(int)), m_simulation, SLOT(updateCameraZoom(int)));
}

void MainApp::refreshControlsFromFluid(const int _fluidId)
{
    //density
    m_ui->spin_fluid_restDensity->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getMaterialRestDensity());

    //gas constant
    m_ui->spin_fluid_gasConstant->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getGasConstant());

    //viscosity constant
    m_ui->spin_fluid_viscosityConstant->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getViscosityConstant());

    //surface tension
    m_ui->spin_fluid_surfaceCoefficient->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getSurfaceTensionCoefficient());
    m_ui->spin_fluid_surfaceThreshold->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getSurfaceTensionThreshold());

    //interface tension
    m_ui->spin_fluid_interfaceCoefficient->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getInterfaceTensionCoefficient());
    m_ui->spin_fluid_interfaceThreshold->setValue(m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getInterfaceTensionThreshold());

    //interface color
    bool minus = m_simulation->getSolver()->getHoseParticlePrototypeList()[_fluidId].getInterfaceColorCoefficient() < 0;
    m_ui->spin_fluid_interfaceColorMinus->setChecked(minus);
    m_ui->spin_fluid_interfaceColorPlus->setChecked(!minus);
}

void MainApp::refreshControlsFromSphere(const int _sphereId)
{
    //position
    m_ui->spin_environment_sphere_centre_x->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getPosition().m_x);
    m_ui->spin_environment_sphere_centre_y->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getPosition().m_y);
    m_ui->spin_environment_sphere_centre_z->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getPosition().m_z);

    //velocity
    m_ui->spin_environment_sphere_velocity_x->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getVelocity().m_x);
    m_ui->spin_environment_sphere_velocity_y->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getVelocity().m_y);
    m_ui->spin_environment_sphere_velocity_z->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getVelocity().m_z);

    //radius
    m_ui->spin_environment_sphere_radius->setValue(m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getRadius());

    //static
    m_ui->chk_environment_sphere_isStatic->setChecked(!m_simulation->getEnvironment()->getSphereObstacleList()[_sphereId].getMoveable());
}

void MainApp::refreshControlsFromCapsule(const int _capsuleId)
{
    //centre
    m_ui->spin_environment_capsule_centre_x->setValue(m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getPosition().m_x);
    m_ui->spin_environment_capsule_centre_y->setValue(m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getPosition().m_y);
    m_ui->spin_environment_capsule_centre_z->setValue(m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getPosition().m_z);

    //angle
    m_ui->spin_environment_capsule_incrementAngle->setValue(m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getIncrementAngle());

    //radius
    m_ui->spin_environment_capsule_radius->setValue(m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getRadius());

    //static
    m_ui->chk_environment_capsule_isStatic->setChecked(!m_simulation->getEnvironment()->getCapsuleObstacleList()[_capsuleId].getMoveable());
}

void MainApp::keyPressEvent(
                               QKeyEvent* _event
                            )
{
    // this method is called every time the main window recives a key event.
    this->setFocus(Qt::ActiveWindowFocusReason);

    switch (_event->key())
    {
        case Qt::Key_Escape : QApplication::exit(EXIT_SUCCESS); break;

        case Qt::Key_M : showFullScreen(); break;
        case Qt::Key_N : showNormal(); break;

        default : break;
    }

    m_simulation->keyPress(_event);
}

//SIMULATION SLOTS
void MainApp::on_cmd_2DTopView_clicked()
{
    //setup top view
    m_simulation->setup2DTopView();
}

void MainApp::on_cmd_2DFrontView_clicked()
{
    //setup front view
    m_simulation->setup2DFrontView();
}

void MainApp::on_chk_cache_enable_clicked(bool checked)
{
    m_simulation->setCacheEnabled(checked);
    m_simulation->toggleCache();
}

void MainApp::on_spin_cache_samplingInterval_valueChanged(int value)
{
    m_simulation->setCacheSamplingInterval(value);
    m_simulation->toggleCache();
}

void MainApp::on_chk_cache_exportRBD_clicked(bool checked)
{
    m_simulation->setCacheExportRBDEnabled(checked);
}

void MainApp::on_chk_cache_exportBoundary_clicked(bool checked)
{
    m_simulation->setCacheExportBoundaryEnabled(checked);
}

void MainApp::on_chk_cache_automaticFlush_clicked(bool checked)
{
    m_simulation->setCacheAutomaticFlushEnabled(checked);
    m_simulation->toggleCache();
}

void MainApp::on_spin_cache_automaticFlushInterval_valueChanged(int value)
{
    m_simulation->setCacheAutomaticFlushInterval(value * 1000);     //s -> ms
    m_simulation->toggleAutomaticCacheFlush();
}

void MainApp::on_chk_fluid_hose_drawMarker_clicked(bool checked)
{
    m_simulation->getSolver()->setDrawHoseMarker(checked);

    m_simulation->updateGL();
}

void MainApp::on_chk_fluid_hose_waitUntilBoundary_clicked(bool checked)
{
    m_simulation->getSolver()->setHoseWaitUntilHitBoundary(checked);
}

void MainApp::on_chk_fluid_hose_waitUntilRBD_clicked(bool checked)
{
    m_simulation->getSolver()->setHoseWaitUntilHitRBD(checked);
}

void MainApp::on_spin_hose_centre_x_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseCenter(ngl::Vector(value, m_simulation->getSolver()->getHoseCenter().m_y, m_simulation->getSolver()->getHoseCenter().m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_hose_centre_y_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseCenter(ngl::Vector(m_simulation->getSolver()->getHoseCenter().m_x, value, m_simulation->getSolver()->getHoseCenter().m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_hose_centre_z_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseCenter(ngl::Vector(m_simulation->getSolver()->getHoseCenter().m_x, m_simulation->getSolver()->getHoseCenter().m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_spin_hose_velocity_x_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseVelocity(ngl::Vector(value, m_simulation->getSolver()->getHoseVelocity().m_y, m_simulation->getSolver()->getHoseVelocity().m_z));
}

void MainApp::on_spin_hose_velocity_y_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseVelocity(ngl::Vector(m_simulation->getSolver()->getHoseVelocity().m_x, value, m_simulation->getSolver()->getHoseVelocity().m_z));
}

void MainApp::on_spin_hose_velocity_z_valueChanged(int value)
{
    m_simulation->getSolver()->setHoseVelocity(ngl::Vector(m_simulation->getSolver()->getHoseVelocity().m_x, m_simulation->getSolver()->getHoseVelocity().m_y, value));
}

void MainApp::on_spin_environment_rbd_restitution_valueChanged(double value)
{
    m_simulation->getEnvironment()->setObstacleRestitutionCoefficient(value);
}

void MainApp::on_spin_environment_capsule_resolution_valueChanged(int value)
{
    m_simulation->getEnvironment()->setCapsuleResolution(value);

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_boundary_centre_x_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryPosition(ngl::Vector(value, m_simulation->getEnvironment()->getBoundaryPosition().m_y, m_simulation->getEnvironment()->getBoundaryPosition().m_z));

    m_simulation->updateGL();
}


void MainApp::on_spin_environment_boundary_centre_y_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryPosition(ngl::Vector(m_simulation->getEnvironment()->getBoundaryPosition().m_x, value, m_simulation->getEnvironment()->getBoundaryPosition().m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_boundary_centre_z_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryPosition(ngl::Vector(m_simulation->getEnvironment()->getBoundaryPosition().m_x, m_simulation->getEnvironment()->getBoundaryPosition().m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_checkBox_clicked(bool checked)
{
    m_simulation->getEnvironment()->setBoundaryBoundTop(checked);
}

void MainApp::on_spin_environment_boundary_restitutionForFluid_valueChanged(double value)
{
    m_simulation->getEnvironment()->setBoundaryRestitutionCoefficientForFluid(value);
}

void MainApp::on_spin_environment_boundary_restitutionForRBD_valueChanged(double value)
{
    m_simulation->getEnvironment()->setBoundaryRestitutionCoefficientForRBD(value);
}

void MainApp::on_chk_environment_boundary_enablePeriodicWall_clicked(bool checked)
{
    m_simulation->getEnvironment()->setPeriodicWallEnabled(checked);
}

void MainApp::on_spin_environment_boundary_periodicWall_maxAmplitude_valueChanged(int value)
{
    m_simulation->getEnvironment()->setPeriodicWallMaxAmplitude(value);
}

void MainApp::on_spin_environment_boundary_periodicWall_speed_valueChanged(double value)
{
    m_simulation->getEnvironment()->setPeriodicWallSpeed(value);
}

void MainApp::on_spin_environment_boundary_periodicWall_angleIncrement_valueChanged(int value)
{
    m_simulation->getEnvironment()->setPeriodicWallAngleIncrement(value);
}

void MainApp::on_spin_environment_boundary_size_x_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryDimension(ngl::Vector(value, m_simulation->getEnvironment()->getBoundaryDimension().m_y, m_simulation->getEnvironment()->getBoundaryDimension().m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_boundary_size_y_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryDimension(ngl::Vector(m_simulation->getEnvironment()->getBoundaryDimension().m_x, value, m_simulation->getEnvironment()->getBoundaryDimension().m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_boundary_size_z_valueChanged(int value)
{
    m_simulation->getEnvironment()->setBoundaryDimension(ngl::Vector(m_simulation->getEnvironment()->getBoundaryDimension().m_x, m_simulation->getEnvironment()->getBoundaryDimension().m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_cmb_environment_sphere_currentIndexChanged(int index)
{
    refreshControlsFromSphere(index);
}

void MainApp::on_cmb_environment_capsule_currentIndexChanged(int index)
{
    refreshControlsFromCapsule(index);
}

void MainApp::on_spin_environment_sphere_centre_x_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updatePosition(ngl::Vector(value, pos.m_y, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_centre_y_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updatePosition(ngl::Vector(pos.m_x, value, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_centre_z_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updatePosition(ngl::Vector(pos.m_x, pos.m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_velocity_x_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get velocity
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getVelocity();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updateVelocity(ngl::Vector(value, pos.m_y, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_velocity_y_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getVelocity();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updateVelocity(ngl::Vector(pos.m_x, value, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_velocity_z_valueChanged(int value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getSphereObstacleList()[id].getVelocity();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].updateVelocity(ngl::Vector(pos.m_x, pos.m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_sphere_radius_valueChanged(double value)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].setRadius(value);

    m_simulation->updateGL();
}

void MainApp::on_chk_environment_sphere_isStatic_clicked(bool checked)
{
    //get currently selected sphere id
    int id = m_ui->cmb_environment_sphere->currentIndex();

    //update currently selected object
    m_simulation->getEnvironment()->getSphereObstacleList()[id].setMoveable(!checked);
}

void MainApp::on_spin_environment_capsule_radius_valueChanged(double value)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].setRadius(value);

    m_simulation->updateGL();
}

void MainApp::on_chk_environment_capsule_isStatic_clicked(bool checked)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].setMoveable(!checked);
}

void MainApp::on_spin_environment_capsule_incrementAngle_valueChanged(int value)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].setIncrementAngle(value);
}

void MainApp::on_spin_environment_capsule_centre_x_valueChanged(double value)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getCapsuleObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].updatePosition(ngl::Vector(value, pos.m_y, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_capsule_centre_y_valueChanged(double value)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getCapsuleObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].updatePosition(ngl::Vector(pos.m_x, value, pos.m_z));

    m_simulation->updateGL();
}

void MainApp::on_spin_environment_capsule_centre_z_valueChanged(double value)
{
    //get currently selected capsule id
    int id = m_ui->cmb_environment_capsule->currentIndex();

    //get position
    ngl::Vector pos = m_simulation->getEnvironment()->getCapsuleObstacleList()[id].getPosition();

    //update currently selected object
    m_simulation->getEnvironment()->getCapsuleObstacleList()[id].updatePosition(ngl::Vector(pos.m_x, pos.m_y, value));

    m_simulation->updateGL();
}

void MainApp::on_spin_solver_timestep_valueChanged(double value)
{
    m_simulation->getIntegration()->setTimestep(value);
}

void MainApp::on_cmb_solver_integrationMethod_currentIndexChanged(int index)
{
    m_simulation->getIntegration()->setIntegrationType(index);
}

void MainApp::on_spin_solver_smoothingLength_valueChanged(double value)
{
    m_simulation->getSolver()->setSmoothingLength(value);
}

void MainApp::on_cmb_fluid_currentFluid_currentIndexChanged(int index)
{
    m_simulation->getSolver()->setCurrentHoseableFluid(index);

    refreshControlsFromFluid(index);
}

void MainApp::on_spin_fluid_restDensity_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateRestDensityForFluid(id, value);
}

void MainApp::on_spin_fluid_gasConstant_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateGasConstantForFluid(id, value);
}

void MainApp::on_spin_fluid_viscosityConstant_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateViscosityConstantForFluid(id, value);
}

void MainApp::on_spin_fluid_surfaceCoefficient_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateSurfaceCoefficientForFluid(id, value);
}

void MainApp::on_spin_fluid_surfaceThreshold_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateSurfaceThresholdForFluid(id, value);
}

void MainApp::on_spin_fluid_interfaceCoefficient_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateInterfaceCoefficientForFluid(id, value);
}

void MainApp::on_spin_fluid_interfaceThreshold_valueChanged(double value)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();

    //update currently selected object
    m_simulation->getSolver()->updateInterfaceThresholdForFluid(id, value);
}

void MainApp::on_spin_fluid_interfaceColorMinus_clicked(bool checked)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();


    if (checked)
        //update currently selected object
        m_simulation->getSolver()->updateInterfaceColorForFluid(id, -0.5);
    else
        //update currently selected object
        m_simulation->getSolver()->updateInterfaceColorForFluid(id, 0.5);

}

void MainApp::on_spin_fluid_interfaceColorPlus_clicked(bool checked)
{
    //get currently selected fluid id
    int id = m_ui->cmb_fluid_currentFluid->currentIndex();


    if (checked)
        //update currently selected object
        m_simulation->getSolver()->updateInterfaceColorForFluid(id, 0.5);
    else
        //update currently selected object
        m_simulation->getSolver()->updateInterfaceColorForFluid(id, -0.5);
}

void MainApp::on_cmd_singleStep_clicked()
{
    m_simulation->getSolver()->updateFluid(m_simulation->getEnvironment(), m_simulation->getIntegration());

    m_simulation->updateGL();
}

void MainApp::on_cmd_autoMove_clicked()
{
    m_ui->cmd_autoMove->setText(!m_simulation->getSolver()->getEnableAutoFluidUpdate() ? "AutoMove Stop" : "AutoMove Start");

    m_simulation->getSolver()->toggleEnableAutoFluidUpdate();
    m_simulation->updateFPSTimer();

    m_simulation->updateGL();
}

void MainApp::on_cmd_flushCache_clicked()
{
    m_simulation->flushCache();
}

void MainApp::on_cmd_injectParticle_clicked()
{
    m_simulation->getSolver()->injectParticles();
}
